#include <math.h>  // M_PI.
#include "zucIniFile.hh"

IniFile::StrIntPair ZucIniFile::jointTypeMap[] = {
    {"LINEAR", ZUC_LINEAR},
    {"ANGULAR", ZUC_ANGULAR},
    {NULL, 0},
};

ZucIniFile::ErrorCode ZucIniFile::Find(ZucJointType* result, const char* tag, const char* section, int num)
{
    return (IniFile::Find((int*)result, jointTypeMap, tag, section, num));
}

IniFile::StrIntPair ZucIniFile::boolMap[] = {
    {"TRUE", 1},
    {"YES", 1},
    {"1", 1},
    {"FALSE", 0},
    {"NO", 0},
    {"0", 0},
    {NULL, 0},
};

ZucIniFile::ErrorCode ZucIniFile::Find(bool* result, const char* tag, const char* section, int num)
{
    ErrorCode errCode;
    int value;

    if ((errCode = IniFile::Find(&value, boolMap, tag, section, num)) == ERR_NONE)
    {
        *result = (bool)value;
    }

    return (errCode);
}

// The next const struct holds pairs for linear units which are
// valid under the [TRAJ] section. These are of the form {"name", value}.
// If the name "name" is encountered in the ini, the value will be used.
ZucIniFile::StrDoublePair ZucIniFile::linearUnitsMap[] = {
    {"mm", 1.0},
    {"metric", 1.0},
    {"in", 1 / 25.4},
    {"inch", 1 / 25.4},
    {"imperial", 1 / 25.4},
    {NULL, 0},
};

ZucIniFile::ErrorCode ZucIniFile::FindLinearUnits(ZucLinearUnits* result, const char* tag, const char* section, int num)
{
    return (IniFile::Find((double*)result, linearUnitsMap, tag, section, num));
}

// The next const struct holds pairs for angular units which are
// valid under the [TRAJ] section. These are of the form {"name", value}.
// If the name "name" is encountered in the ini, the value will be used.
ZucIniFile::StrDoublePair ZucIniFile::angularUnitsMap[] = {
    {"deg", 1.0},
    {"degree", 1.0},
    {"grad", 0.9},
    {"gon", 0.9},
    {"rad", M_PI / 180},
    {"radian", M_PI / 180},
    {NULL, 0},
};

ZucIniFile::ErrorCode ZucIniFile::FindAngularUnits(ZucAngularUnits* result, const char* tag, const char* section, int num)
{
    return (IniFile::Find((double*)result, angularUnitsMap, tag, section, num));
}

ZucIniFile::ErrorCode ZucIniFile::FindArray(double* arrRes, int arrNum, const char* tag, const char* section, int num)
{
    std::string resString("");
    ErrorCode errCode;

    if (arrRes == nullptr)
    {
        return ERR_OVER_EXTENDED;
    }

    if ((errCode = IniFile::Find(&resString, tag, section, num)) == ERR_NONE)
    {
        // printf("section = %s, tag is %s, resstring = %s\n", section, tag, resString.c_str());
        std::vector<std::string> optList;
        resString.erase(0, resString.find_first_not_of("{"));
        resString.erase(resString.find_last_not_of("}") + 1);

        optList = split(resString, ',');
        for (int i = 0; i < arrNum && i < (int)optList.size(); i++) { arrRes[i] = std::stof(optList[i]); }
    }

    return errCode;
}

ZucIniFile::ErrorCode ZucIniFile::FindArray(int* arrRes, int arrNum, const char* tag, const char* section, int num)
{
    std::string resString("");
    ErrorCode errCode;

    if (arrRes == nullptr)
    {
        return ERR_OVER_EXTENDED;
    }

    if ((errCode = IniFile::Find(&resString, tag, section, num)) == ERR_NONE)
    {
        std::vector<std::string> optList;
        resString.erase(0, resString.find_first_not_of("{"));
        resString.erase(resString.find_last_not_of("}") + 1);

        optList = split(resString, ',');
        for (int i = 0; i < arrNum && i < (int)optList.size(); i++) { arrRes[i] = std::stoi(optList[i]); }
    }

    return errCode;
}

ZucIniFile::ErrorCode ZucIniFile::FindArray(float* arrRes, int arrNum, const char* tag, const char* section, int num)
{
    std::string resString("");
    ErrorCode errCode;

    if (arrRes == nullptr)
    {
        return ERR_OVER_EXTENDED;
    }

    if ((errCode = IniFile::Find(&resString, tag, section, num)) == ERR_NONE)
    {
        std::vector<std::string> optList;
        resString.erase(0, resString.find_first_not_of("{"));
        resString.erase(resString.find_last_not_of("}") + 1);

        optList = split(resString, ',');
        for (int i = 0; i < arrNum && i < (int)optList.size(); i++) { arrRes[i] = std::stof(optList[i]); }
    }

    return errCode;
}
